use std::sync::{Arc, LazyLock};

use parking_lot::Mutex;
use peer::Peer;
use round_robin::RoundRobin;

use crate::config::backend::{BackendConf, BackendServerConf};
use crate::error::*;

pub mod peer;
pub mod round_robin;

#[allow(dead_code)]
pub enum BalanceType {
    RoundRobin,
    Chash,
}

#[allow(dead_code)]
pub struct BalanceParams {}

#[allow(dead_code)]
pub struct Backend {
    pub backend_conf: Arc<BackendConf>,
    pub peers: Vec<Arc<Peer>>,
    pub backend_peers: Vec<Arc<Peer>>,
    pub balance_type: BalanceType,
    rr_balance: Option<Mutex<RoundRobin>>,
    // chash_balance: Option<Mutex<Chash>>,
}

#[allow(dead_code)]
impl Backend {
    pub fn build(backend_conf: Arc<BackendConf>) -> Result<Self> {
        // TODO...
        Ok(Backend {
            backend_conf,
            peers: Vec::new(),
            backend_peers: Vec::new(),
            balance_type: BalanceType::RoundRobin,
            rr_balance: None,
        })

        // todo!()
    }

    // FIXME
    pub async fn get_peer(
        &self,
        params: Option<&BalanceParams>,
    ) -> Result<Arc<Peer>> {
        _ = params;

        let server_conf = BackendServerConf {
            address: "127.0.0.1".to_string(),
            port: Some(8888),
            ..Default::default()
        };

        let peer = Peer::create_by_conf(server_conf).unwrap();
        Ok(Arc::new(peer))
    }
}

#[allow(dead_code)]
pub struct BackendsMgr {}

#[allow(dead_code)]
impl BackendsMgr {
    pub fn get_instance() -> &'static BackendsMgr {
        static BACKENDS_MGR: LazyLock<BackendsMgr> =
            LazyLock::new(|| BackendsMgr {});
        &BACKENDS_MGR
    }

    pub fn get_backend(_backend_name: &str) -> Option<Arc<Backend>> {
        None
    }
}
